package com.xiaodu.rest.controller;

import com.google.common.io.Files;
import com.xiaodu.rest.entity.UserEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: dutianjie
 * @date: 2021/4/13
 * @version: v1.0.0
 * @description:  模拟请求 jdbcTemplate工程，需要启动jdbcTemplate项目
 **/
@RestController
@RequestMapping("user")
@Api(tags = {"用户操作"})
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    @Qualifier("restTemplateOkHttpClient")
    RestTemplate restTemplateOkHttpClient;


    private static final String JDBC_DEMO_URL = "http://localhost:8989";

    @ApiOperation(httpMethod = "GET", value = "通过restTemplate调用其他服务获取user信息")
    @GetMapping("{id}")
    public UserEntity getUser(@ApiParam(required = true, name = "id", value = "userId") @PathVariable String id) throws Exception {
        //getForObject
        return restTemplate.getForObject(JDBC_DEMO_URL + "/user/" + id, UserEntity.class);
    }

    @ApiOperation(httpMethod = "GET", value = "通过restTemplate调用其他服务获取user信息")
    @GetMapping("batch")
    public List<UserEntity> getBatchUser(@ApiParam(required = true, name = "ids", value = "userId") @RequestParam(name = "ids") String[] ids) throws Exception {
        //getForObject to list  使用 模板占位符 {index}；进行传参，Object... uriVariables 按照index顺序进行传参
        List<String> params = new LinkedList<>();
        for (int i = 0; i < ids.length; i++) {
            params.add("{" + i + "}");
        }
        String collect = params.stream().collect(Collectors.joining("&ids=", "?ids=", ""));
        return restTemplate.getForObject(JDBC_DEMO_URL + "/user/batch" + collect, List.class, ids);
    }

    @ApiOperation(value = "批量添加", httpMethod = "POST")
    @PostMapping("batch")
    public List<String> batchAddUser(@RequestBody List<UserEntity> userEntities) throws Exception {
//        return restTemplate.postForObject(JDBC_DEMO_URL + "/user/batch", userEntities, List.class);
        return restTemplateOkHttpClient.postForObject(JDBC_DEMO_URL + "/user/batch", userEntities, List.class);
    }

    @ApiOperation(value = "添加用户信息", httpMethod = "POST", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @PostMapping()
    public String addUser(@RequestBody UserEntity userEntity) throws Exception {
        // 模拟form 表单提交，form 表单提交body 需要为 MultiValueMap
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, Object> p = new LinkedMultiValueMap<>();
        p.add("uName", userEntity.getuName());
        p.add("password", userEntity.getPassword());
        p.add("money", userEntity.getMoney());
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(p, headers);
        return restTemplate.postForEntity(JDBC_DEMO_URL + "/user", httpEntity, String.class).getBody();
    }

    @ApiOperation(value = "根据id更新", httpMethod = "PUT")
    @PutMapping()
    public void updateUser(@RequestBody UserEntity userEntity) throws Exception {
        Objects.requireNonNull(userEntity.getuId());
        restTemplate.put(JDBC_DEMO_URL + "/user", userEntity);
        // 也可以使用 exchange
//        restTemplate.exchange(JDBC_DEMO_URL + "/user", HttpMethod.PUT, new HttpEntity<>(userEntity), Void.class);
    }

    @ApiOperation(value = "根据id删除", httpMethod = "DELETE")
    @DeleteMapping
    public void delateUser(@RequestParam(name = "id") String id) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put("id", id);
        // 使用{field}占位符,进行参数映射
        restTemplate.delete(JDBC_DEMO_URL + "/user/{id}", map);
    }


    /*-----------------------restTemplate 操作文件上传----------------------------------*/

    @PostMapping("file")
    @ApiOperation(value = "上传文件", httpMethod = "POST")
    public void upload(MultipartFile file) throws Exception {
        uploadByFileSystemResource(file);

    }

    // 通过fileSystemResource 进行文件上传, 使用multipartFile 接收;缺点需要通过创建临时文件上传,以及使用完后不能再次使用
    private void uploadByFileSystemResource(MultipartFile file) throws Exception {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        File tempFile = new File(Files.createTempDir().getPath() + "/" + file.getOriginalFilename());
        file.transferTo(tempFile);
        FileSystemResource fileSystemResource = new FileSystemResource(tempFile);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("file", fileSystemResource);
        HttpEntity httpEntity = new HttpEntity<>(param, headers);
        restTemplate.postForEntity(JDBC_DEMO_URL + "/user/file", httpEntity, Void.class);
    }

    @SuppressWarnings("all")
    // 通过InputStreamResource 上传， 通过request.getInputStream 接收
    private void uploadByInputStreamResource(MultipartFile file) throws Exception {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.parseMediaType(file.getContentType()));
        InputStreamResource inputStreamResource = new InputStreamResource(file.getInputStream());
        HttpEntity httpEntity = new HttpEntity<>(inputStreamResource, httpHeaders);
        restTemplate.postForEntity(JDBC_DEMO_URL + "/user/file2", httpEntity, Void.class);

    }

    // 通过byteArrayResource  上传，  通过request.getInputStream 接收
    @SuppressWarnings("all")
    private void uploadByByteArrayResource(MultipartFile file) throws Exception {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType(file.getContentType()));
        ByteArrayResource byteArrayResource = new ByteArrayResource(file.getBytes());
        HttpEntity httpEntity = new HttpEntity<>(byteArrayResource, headers);
        restTemplate.postForEntity(JDBC_DEMO_URL + "/user/file2", httpEntity, Void.class);
    }

    // 通过MultipartFile 接收，而不想使用FileSystemResource(需要创建临时文件)
    private void uploadBy(MultipartFile file) throws Exception {
        // ByteArrayResource 和InputStreamResource 都可以
        ByteArrayResource byteArrayResource = new ByteArrayResource(file.getBytes());
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.parseMediaType(Objects.requireNonNull(file.getContentType())));
        httpHeaders.setContentDispositionFormData("file", file.getOriginalFilename());
        HttpEntity<ByteArrayResource> bodyHttpEntity = new HttpEntity<>(byteArrayResource, httpHeaders);
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("file", bodyHttpEntity);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(body, headers);
        restTemplate.postForEntity(JDBC_DEMO_URL + "/user/file", httpEntity, Void.class);
    }
}
